首先在註冊流程中,新增帳號後方加上寄出認證信吧
// 新增到資料庫
$data_array = array(
'username' => $username,
'password' => $hashedpassword,
'email' => $email,
'active' => $activasion
);
Database::get()->insert("members", $data_array);
//以下是新的代碼
$id = Database::get()->getLastId(); // 取得最後新增的 member ID
$subject = "Registration Confirmation";
$body = "<p>Thank you for registering at demo site.</p>
<p>To activate your account, please click on this link: <a href='".Config::BASE_URL."activate/$id/$activasion'>".Config::BASE_URL."activate/$id/$activasion</a></p>
<p>Regards Site Admin</p>"; // 這邊用網址上的 GET 參數讓他回來網站時夾帶驗證碼
$mail = new Mail(Config::MAIL_USER_NAME, Config::MAIL_USER_PASSWROD);
$mail->setFrom(Config::MAIL_FROM, Config::MAIL_FROM_NAME);
$mail->addAddress($email);
$mail->subject($subject);
$mail->body($body);
$mail->send(); // 透過 GMAIL 送出
因為
Config::BASE_URL."activate/$id/$activasion"
所以送出後信件內的網址會是 http://127.0.0.1/game/activate/數字/亂碼
我們要在 activate 這個網址準備接收這兩組來驗證後開通帳號
所以在 route.php 要開新的 case
switch($route->getParameter(1)){
case "activate";
$data_array = array();
$data_array['memberID'] = $route->getParameter(2);
$data_array['active'] = $route->getParameter(3);
$gump = new GUMP();
$data_array = $gump->sanitize($data_array);
$validation_rules_array = array(
'memberID' => 'required|integer',
'active' => 'required|exact_len,32'
);
$gump->validation_rules($validation_rules_array);
$filter_rules_array = array(
'memberID' => 'trim|sanitize_string',
'active' => 'trim',
);
$gump->filter_rules($filter_rules_array);
$validated_data = $gump->run($data_array);
if($validated_data === false) {
//$error = $gump->get_readable_errors(false);
exit;
} else {
foreach($validation_rules_array as $key => $val) {
${$key} = $data_array[$key];
}
$userVeridator = new UserVeridator();
if($userVeridator->isReady2Active($id, $active)){
$data_array['active'] = "Yes";
Database::get()->update("members", $data_array, "memberID", $data_array['memberID']);
header('Location: login?action=active');
exit;
}else{
echo "Your account could not be activated.";
exit;
}
}
break;
}
邏輯上需要先驗證這組帳號是否存在,並且驗證碼相符,才能開通他。所以加上 isReady2Active 這個 function來使用
UserVeridator.php
/**
* 驗證此帳號 ID 跟 開通碼 hash 是否已存在於資料庫中
*/
public function isReady2Active($id, $active){
$result = Database::get()->execute('SELECT username FROM members WHERE memberID = :memberID AND active = :active', array(':memberID' => $id, ':active' => $active));
if(isset($result[0]['username']) and !empty($result[0]['username'])){
return true;
}else{
$this->error[] = 'Username provided is already in use.';
return false;
}
}
這樣一來就可以確認開通後 送到 login 畫面了
但是還要再補一個地方,之前我們做登入時沒有驗證 active 是否等於 Yes
所以再更新一次 UserVeridator 的 loginVerification function
UserVeridator.php
/**
* 驗證帳號密碼是否正確可登入
*/
public function loginVerification($username, $password){
$result = Database::get()->execute('SELECT * FROM members WHERE active = "Yes" AND username = :username', array(':username' => $username));
if(isset($result[0]['memberID']) and !empty($result[0]['memberID'])) {
$passwordObject = new Password();
if($passwordObject->password_verify($password,$result[0]['password'])){
return true;
}
}
$this->error[] = 'Wrong username or password or your account has not been activated.';
return false;
}
大功告成!
感謝樓主分享,受益良多
提醒一下
如果 memberID 欄位設定為 AUTO_INCREMENT 自動累加
更新資料庫的時候如果把整個 $data_array 送進去會報錯,因為 ID 不可被更新
Database::get()->update("members", $data_array, "memberID", $data_array['memberID']);
// 報錯
更改為
Database::get() -> update("user", array('active' => 'Yes'), "id", $data_array['memberID']);
// 可執行
感謝樓主分享
在route.php新增activate case中
前面使用${$key}這方式來獲得$memberID和$active
但後面使用isReady2Active($id,$active)這裡筆誤了
if($userVeridator->isReady2Active($id, $active)){ // 這裡沒有 $id的變數
需要改為
if($userVeridator->isReady2Active($memberID, $active)){
再根據上一位的講解做修改就能順利執行了